<?php
class Menu extends Dao
{
	private static $_instance = null;
	protected $_db = null, $_cache = null;
	
	protected function __construct()
	{
		parent::__construct();
	}
	
	public static function getInstance() 
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
	
	
	public function getList(array $args = array(), $intPage = 1, $intLimit = MIN_ROWS_PER_PAGE)
	{
		try{
			$defaults = array(			
			);
			$args = $this->args_merge($defaults, $args);
			
			$intStart = ($intPage-1)*$intLimit;

			$strSql = " SELECT SQL_CALC_FOUND_ROWS menu_id, menu_name, menu_title, menu_description, menu_status
						FROM tbl_menu
						LIMIT :intStart, :intLimit";
			
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":intStart",$intStart,PDO::PARAM_INT);
			$cmd->bindParam(":intLimit",$intLimit,PDO::PARAM_INT);
			
			$arrResults = $cmd->queryAll();
			if(!empty($arrResults)){
				$arrResults[0]['total_rows'] = $this->_db->createCommand('SELECT FOUND_ROWS();')->queryScalar();
			}
			return $arrResults;
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
		
	public function get($id)
	{
		try{
			$strSql = " SELECT menu_id, menu_name, menu_title, menu_description, menu_status
						FROM tbl_menu
						WHERE menu_id=:id";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":id",$id,PDO::PARAM_STR);
			return $arrResults = $cmd->queryRow();
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function getByCode($code)
	{
		try{
			$strSql = " SELECT menu_id, menu_name, menu_title, menu_description, menu_status
						FROM tbl_menu
						WHERE menu_name=:code";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":code",$code,PDO::PARAM_STR);
			return $arrResults = $cmd->queryRow();
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function insert(array $args)
	{		
		try{
			$defaults = array(
				'menu_name' => null,
				'menu_title' => null,
				'menu_description' => null,
				'menu_status' => null	
			);
			$args = $this->args_merge($defaults, $args);
			
			$cmd = $this->_db->createCommand();
			$cmd->insert('tbl_menu',$args);
			return Yii::app()->db->getLastInsertId();
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function update($id, array $args)
	{		
		try{
			$defaults = array(
				'menu_name' => null,
				'menu_title' => null,
				'menu_description' => null,
				'menu_status' => null				
			);
			$args = $this->args_merge($defaults, $args);
			
			$cmd = $this->_db->createCommand();
			return $cmd->update('tbl_menu',$args, 'menu_id=:id', array(':id'=>$id));
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
		
	public function delete($id){
		try{
			//delete menu item first
			$cmd = $this->_db->createCommand();
			$cmd->delete('tbl_menu_items', 'menu_id=:id', array(':id'=>$id));
			//delete menu
			$cmd = $this->_db->createCommand();
			return $cmd->delete('tbl_menu', 'menu_id=:id', array(':id'=>$id));			
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function listItems($intMenuId, $intRecursiveLevel = 255){
		try{
			/*$strSql = " SELECT item_id, item_title, item_image, item_link, item_description, item_linktarget, item_position, item_status, item_parent
						FROM tbl_menu_items
						WHERE menu_id=:id";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":id",$intMenuId,PDO::PARAM_STR);
			return $arrResults = $cmd->queryRow();*/
			
			if($intRecursiveLevel < 0) $intRecursiveLevel = 0;
			if($intRecursiveLevel > 255) $intRecursiveLevel = 255;
			$arrResults = array();
			return $arrResults = $this->_listItems(0, $intMenuId, null, $intRecursiveLevel, $arrResults);
			
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	private function _listItems($intCurrentLevel = 0, $intMenuId, $intParentItemId, $intRecursiveLevel, &$arrResults){
		if($intParentItemId === null){
				$cmd = $this->_db->createCommand("SELECT * FROM tbl_menu_items WHERE menu_id = :menu AND item_parent IS NULL ORDER BY item_position ASC");
			} else {
				$cmd = $this->_db->createCommand("SELECT * FROM tbl_menu_items WHERE menu_id = :menu AND item_parent = :id ORDER BY item_position ASC");
				$cmd->bindParam(':id', $intParentItemId, PDO::PARAM_INT);
			}
			$cmd->bindParam(':menu', $intMenuId, PDO::PARAM_INT);
			$arrTemp = $cmd->queryAll();
			//count child
			if(!empty($arrResults)){
				end($arrResults);
				$last=key($arrResults);
				$arrResults[$last]['item_num_children'] = count($arrTemp);
			}
			//
			foreach($arrTemp as $R){
					$R['item_level'] = $intCurrentLevel;
					$arrResults[] = $R;
					if($intCurrentLevel < $intRecursiveLevel){
						$this->_listItems($intCurrentLevel+1, $intMenuId, $R['item_id'], $intRecursiveLevel, $arrResults);
					}
			}
			return $arrResults;
	}
	
	public function insertItem(array $args){
		try{
			$defaults = array(
				'menu_id' => null,
				'item_title' => null,
				'item_image' => null,
				'item_link' => null,
				'item_description' => null,
				'item_linktarget' => null,
				'item_position' => null,
				'item_status' => null,
				'item_parent' => null			
			);
			$args = $this->args_merge($defaults, $args, true);
			
			$cmd = $this->_db->createCommand();
			$cmd->insert('tbl_menu_items',$args);
			return Yii::app()->db->getLastInsertId();
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function updateItem($intId, array $args){
		try{
			$defaults = array(
				'menu_id' => null,
				'item_title' => null,
				'item_image' => null,
				'item_link' => null,
				'item_description' => null,
				'item_linktarget' => null,
				'item_position' => null,
				'item_status' => null,
				'item_parent' => null			
			);
			$args = $this->args_merge($defaults, $args);
			
			$cmd = $this->_db->createCommand();
			return $cmd->update('tbl_menu_items',$args, 'item_id=:id', array(':id'=>$id));
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function updateHierarchy(array $args){
		try{
			/*TODO: CHECK TRIGGER HERE*/
			$cmd = $this->_db->createCommand();
			/*remove old hierarchy*/
			$cmd->update('tbl_menu_items', array('item_parent'=>null));
			/*fetch parents*/
			foreach($args as $parent => $items){
				/*fetch child*/
				foreach($items as $order=>$id){
					if(!empty($id)){
						/*update new hierarchy for childen*/
						$cmd->update('tbl_menu_items', array('item_parent'=>$parent, 'item_position'=>$order+1), 'item_id=:id', array(':id'=>$id));
					}
				}
			}
			
			/*find root parents*/
			$arr = array();
			$parent = array_keys($args);
			foreach($parent as $k=>$id_parent){
				foreach($args as $children){				
					if(in_array($id_parent, $children)) { unset($parent[$k]); break; }
				}
			}
			/*update new hierarchy for root parents*/
			foreach($parent as $order=>$id){
				$cmd->update('tbl_menu_items', array('item_parent'=>null, 'item_position'=>$order+1), 'item_id=:id', array(':id'=>$id));
			}
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
}